6300 // Intel 8259A programmable interrupt controllers.
6301 
6302 #include "types.h"
6303 #include "x86.h"
6304 #include "traps.h"
6305 
6306 // I/O Addresses of the two programmable interrupt controllers
6307 #define IO_PIC1         0x20    // Master (IRQs 0-7)
6308 #define IO_PIC2         0xA0    // Slave (IRQs 8-15)
6309 
6310 #define IRQ_SLAVE       2       // IRQ at which slave connects to master
6311 
6312 // Current IRQ mask.
6313 // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
6314 static ushort irqmask = 0xFFFF & ~(1<<IRQ_SLAVE);
6315 
6316 static void
6317 picsetmask(ushort mask)
6318 {
6319   irqmask = mask;
6320   outb(IO_PIC1+1, mask);
6321   outb(IO_PIC2+1, mask >> 8);
6322 }
6323 
6324 void
6325 picenable(int irq)
6326 {
6327   picsetmask(irqmask & ~(1<<irq));
6328 }
6329 
6330 // Initialize the 8259A interrupt controllers.
6331 void
6332 picinit(void)
6333 {
6334   // mask all interrupts
6335   outb(IO_PIC1+1, 0xFF);
6336   outb(IO_PIC2+1, 0xFF);
6337 
6338   // Set up master (8259A-1)
6339 
6340   // ICW1:  0001g0hi
6341   //    g:  0 = edge triggering, 1 = level triggering
6342   //    h:  0 = cascaded PICs, 1 = master only
6343   //    i:  0 = no ICW4, 1 = ICW4 required
6344   outb(IO_PIC1, 0x11);
6345 
6346   // ICW2:  Vector offset
6347   outb(IO_PIC1+1, T_IRQ0);
6348 
6349 
6350   // ICW3:  (master PIC) bit mask of IR lines connected to slaves
6351   //        (slave PIC) 3-bit # of slave's connection to master
6352   outb(IO_PIC1+1, 1<<IRQ_SLAVE);
6353 
6354   // ICW4:  000nbmap
6355   //    n:  1 = special fully nested mode
6356   //    b:  1 = buffered mode
6357   //    m:  0 = slave PIC, 1 = master PIC
6358   //      (ignored when b is 0, as the master/slave role
6359   //      can be hardwired).
6360   //    a:  1 = Automatic EOI mode
6361   //    p:  0 = MCS-80/85 mode, 1 = intel x86 mode
6362   outb(IO_PIC1+1, 0x3);
6363 
6364   // Set up slave (8259A-2)
6365   outb(IO_PIC2, 0x11);                  // ICW1
6366   outb(IO_PIC2+1, T_IRQ0 + 8);      // ICW2
6367   outb(IO_PIC2+1, IRQ_SLAVE);           // ICW3
6368   // NB Automatic EOI mode doesn't tend to work on the slave.
6369   // Linux source code says it's "to be investigated".
6370   outb(IO_PIC2+1, 0x3);                 // ICW4
6371 
6372   // OCW3:  0ef01prs
6373   //   ef:  0x = NOP, 10 = clear specific mask, 11 = set specific mask
6374   //    p:  0 = no polling, 1 = polling mode
6375   //   rs:  0x = NOP, 10 = read IRR, 11 = read ISR
6376   outb(IO_PIC1, 0x68);             // clear specific mask
6377   outb(IO_PIC1, 0x0a);             // read IRR by default
6378 
6379   outb(IO_PIC2, 0x68);             // OCW3
6380   outb(IO_PIC2, 0x0a);             // OCW3
6381 
6382   if(irqmask != 0xFFFF)
6383     picsetmask(irqmask);
6384 }
6385 
6386 
6387 
6388 
6389 
6390 
6391 
6392 
6393 
6394 
6395 
6396 
6397 
6398 
6399 
